package org.jvm.rtda.heap.classmember;

import org.jvm.classfile.MemberInfo;
import org.jvm.rtda.heap.*;

/**
 * 类成员，包含类字段和方法
 *
 * @author 王思翔
 * @date 2023/2/4
 */
public class ClassMember {
    /**
     * 类成员访问标识
     */
    protected int accessFlags;

    /**
     * 类成员名称
     */
    protected String name;

    /**
     * 类成员描述符
     */
    protected String descriptor;

    /**
     * 类成员所属类信息
     */
    protected Klass klass;

    protected byte[] annotationData;

    public ClassMember(Klass klass, MemberInfo memberInfo) {
        this.klass = klass;
        this.accessFlags = memberInfo.getAccessFlags();
        this.name = memberInfo.name();
        this.descriptor = memberInfo.descriptor();
        this.annotationData = memberInfo.getRuntimeVisibleAnnotationsAttributeData();
    }

    public ClassMember() {
    }

    /**
     * 检查本类成员是否可以被其他类访问
     *
     * @param thatClass 其他类
     * @return
     */
    public boolean isAccessibleTo(Klass thatClass) {
        //公共级别成员可以运行任何类访问
        if (isPublic()) {
            return true;
        }
        //私有级别成员仅允许自身类访问
        if (isPrivate()) {
            return thatClass == this.klass;
        }
        boolean isSamePackage = this.klass.getPackageName().equals(thatClass.getPackageName());
        //默认级别成员仅允许同包访问
        if (!isProtected()) {
            return isSamePackage;
        }
        //保护级别成员允许同包或本类子类访问
        return isSamePackage || thatClass.isSubClassOf(this.klass);
    }

    public Boolean isPublic() {
        return (this.accessFlags & AccessFlags.ACC_PUBLIC.getCode()) > 0;
    }

    public Boolean isPrivate() {
        return (this.accessFlags & AccessFlags.ACC_PRIVATE.getCode()) > 0;
    }

    public Boolean isProtected() {
        return (this.accessFlags & AccessFlags.ACC_PROTECTED.getCode()) > 0;
    }

    public Boolean isStatic() {
        return (this.accessFlags & AccessFlags.ACC_STATIC.getCode()) > 0;
    }

    public Boolean isFinal() {
        return (this.accessFlags & AccessFlags.ACC_FINAL.getCode()) > 0;
    }

    public Boolean isSynthetic() {
        return (this.accessFlags & AccessFlags.ACC_SYNTHETIC.getCode()) > 0;
    }

    public int getAccessFlags() {
        return accessFlags;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescriptor() {
        return descriptor;
    }

    public void setDescriptor(String descriptor) {
        this.descriptor = descriptor;
    }

    public Klass getKlass() {
        return klass;
    }

    public void setKlass(Klass klass) {
        this.klass = klass;
    }

    public String signature() {
        return "";
    }

    public byte[] getAnnotationData() {
        return annotationData;
    }

}
